#include <bits/stdc++.h>

using namespace std;
#define ull unsigned long long
typedef struct Node
{
    int c, w; // c个w
    Node(int c, int w) : c(c), w(w) {}
} Node;

typedef struct MyStack
{
    vector<ull> preSum;   // 前缀和 总和
    vector<ull> preCount; // 前缀和 个数
    vector<pair<int, int>> nodes;
    void resize(int _size)
    {
        if (_size == 0)
        {
            // 清空 x 并释放内存
            vector<ull>().swap(preSum);
            vector<ull>().swap(preCount);
            vector<pair<int, int>>().swap(nodes);
            preSum.push_back(0);
            preCount.push_back(0);
            nodes.push_back({0, 0});
        }
        preSum.resize(1 + _size);
        preCount.resize(1 + _size);
        nodes.resize(1 + _size);
    }
    MyStack()
    {
        // 哨兵节点
        preSum.push_back(0);
        preCount.push_back(0);
        nodes.push_back({0, 0});
    }
    ull insert(int c, int w)
    { // 插入 c 个 w 返回总和
        if (nodes.rbegin()->second == w)
        {
            nodes.rbegin()->first += c;
            preCount[preCount.size() - 1] += c;
            return preSum[preSum.size() - 1] += (ull)c * w;
            //  *preSum.rbegin();
        }
        ull nodeSum = (ull)c * w;
        nodes.push_back({c, w});
        preCount.push_back(c + *preCount.rbegin());
        preSum.push_back(nodeSum + *preSum.rbegin());
        return *preSum.rbegin();
    }
    ull pop(int c)
    {
        //
        ull curSum = *preSum.rbegin();
        ull curCount = *preCount.rbegin();
        ull searchCount = curCount - c;
        if (searchCount == 0)
        { // 全部删除
            this->resize(0);
            return curSum;
        }
        auto nodeIt = lower_bound(
            preCount.begin(), preCount.end(), searchCount);
        int nodeIdx = distance(preCount.begin(), nodeIt);
        auto processed = nodes[nodeIdx];
        ull shouldDel = preCount[nodeIdx] - searchCount;
        ull ans = *preSum.rbegin() - preSum[nodeIdx];
        if (shouldDel == 0)
        {
            this->resize(nodeIdx);
            return ans;
        }
        // 处理内部
        ans += shouldDel * processed.second;

        // 更新前缀
        nodes[nodeIdx].first -= shouldDel;
        preSum[nodeIdx] -= shouldDel * processed.second;
        preCount[nodeIdx] -= shouldDel;

        this->resize(nodeIdx);
        return ans;
    }
} MyStack;
ull move(MyStack &x, MyStack &y)
{
    for (auto p = x.nodes.rbegin(); p != x.nodes.rend() - 1; p = next(p))
    {
        y.insert(p->first, p->second);
    }
    x.resize(0);
    return *y.preSum.rbegin();
}
MyStack mStack[200'001];

int main()
{
    int n, m;
    cin >> n >> m;
    while (m--)
    {
        int code;
        cin >> code;
        if (code == 1)
        {
            int x, w, c;
            cin >> x >> w >> c;
            cout << mStack[x].insert(c, w);
        }
        else if (code == 2)
        {
            int x, c;
            cin >> x >> c;
            cout << mStack[x].pop(c);
        }
        else if (code == 3)
        {
            int x, y;
            cin >> x >> y;
            cout << move(mStack[x], mStack[y]);
        }
        cout << endl;
    }

    // system("pause");
    return 0;
}
